package cn.acmenms.manager.authorization;

import cn.acmenms.exception.TokenException;
import cn.acmenms.po.vo.TokenUser;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @ClassName: TokenManager
 * @Description: REST鉴权-登录用户的身份鉴权-JWT
 * @author: 神奇的鸭鸭
 * @Date: 2017/12/28 15:01
 */
public class JwtTokenManager implements TokenManager {

    private Logger logger = LoggerFactory.getLogger(JwtTokenManager.class);

    private static final String SECRET_KEY = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";

    private static final String USER = "USER";
    private static final String EXP = "EXP";

    @Override
    public String createToken(TokenUser user, Long expTime) throws TokenException {
        ObjectMapper mapper = new ObjectMapper();
        // 转成json方便直接转JAVABEAN，默认会将所有字段存为LinkedHashMap
        try {
            String jsonString = mapper.writeValueAsString(user);
            return Jwts.builder()
                    .signWith(SignatureAlgorithm.HS512, SECRET_KEY) // SECRET_KEY是加密算法对应的密钥，这里使用的是HS256加密算法
                    .claim(USER, jsonString)
                    .claim(EXP, expTime) // expTime是过期时间
                    .compact();
        } catch (Exception e) {
            logger.error("创建token失败", user, expTime);
            throw new TokenException("创建token失败");
        }
    }

    @Override
    public TokenUser checkToken(String token) throws TokenException {
        try {
            // 解析JWT字符串中的数据，并进行最基础的验证
            Claims claims = Jwts.parser()
                    .setSigningKey(SECRET_KEY) //SECRET_KEY是加密算法对应的密钥 jwt可以自动判断机密算法
                    .parseClaimsJws(token) // token是JWT字符串
                    .getBody();
            // 校验解析后的数据
            if (claims.containsKey(EXP) && claims.containsKey(USER)) {
                // 过期时间
                long exp = Long.valueOf(claims.get(EXP).toString());
                // 当前时间
                long currentTimeMillis = System.currentTimeMillis();
                String jsonString = (String) claims.get(USER);
                if (exp > currentTimeMillis && null != jsonString && !"".equals(jsonString.trim())) {
                    ObjectMapper mapper = new ObjectMapper();
                    return mapper.readValue(jsonString, TokenUser.class);
                }
            }
        } catch (Exception e) {
            logger.error("Token是无效的", token);
            throw new TokenException("token是无效的");
        }
        return null;
    }
}